#fenv.h
这个头文件提供 浮点数环境 的相关功能,例如浮点异常处理、舍入方向控制等。
需要链接数学库,例如在 gcc 中需要添加
-lm
链接选项。
浮点环境功能依赖于硬件和编译器的具体实现,可能需要手动开启:
通过
#pragma STDC FENV_ACCESS ON
预处理指令可以开启浮点环境功能。通过
#pragma STDC FENV_ACCESS OFF
预处理指令可以关闭浮点环境功能。部分硬件或编译器可能不支持。
示例:
#include <stdio.h>
#include <fenv.h>
#include <math.h>
#include <errno.h>
void show_exceptions(void) {
printf("当前浮点异常状态: ");
if (fetestexcept(FE_ALL_EXCEPT) == 0) {
printf("无异常\n");
return;
}
if (fetestexcept(FE_DIVBYZERO)) printf("除零异常 ");
if (fetestexcept(FE_INVALID)) printf("无效操作异常 ");
if (fetestexcept(FE_OVERFLOW)) printf("上溢异常 ");
if (fetestexcept(FE_UNDERFLOW)) printf("下溢异常 ");
if (fetestexcept(FE_INEXACT)) printf("不精确结果异常 ");
printf("\n");
}
void show_rounding_mode(void) {
printf("当前舍入模式: ");
switch (fegetround()) {
case FE_TONEAREST: printf("四舍五入\n"); break;
case FE_DOWNWARD: printf("向负无穷方向舍入\n"); break;
case FE_UPWARD: printf("向正无穷方向舍入\n"); break;
case FE_TOWARDZERO: printf("向零舍入\n"); break;
default: printf("未知模式\n");
}
}
int main() {
// 1. 显示初始浮点环境
printf("=== 初始浮点环境 ===\n");
show_exceptions();
show_rounding_mode();
printf("\n");
// 2. 触发浮点异常示例
printf("=== 触发浮点异常 ===\n");
feclearexcept(FE_ALL_EXCEPT); // 清除所有异常标志
// 除零异常
double x = 1.0, y = 0.0;
double z = x / y;
printf("1.0 / 0.0 = %f\n", z);
show_exceptions();
// 无效操作异常
double a = sqrt(-1.0);
printf("sqrt(-1.0) = %f\n", a);
show_exceptions();
printf("\n");
// 3. 舍入模式控制示例
printf("=== 舍入模式控制 ===\n");
fesetround(FE_DOWNWARD); // 设置为向负无穷舍入
show_rounding_mode();
double num = 1.75;
printf("1.75 舍入后: %f\n", rint(num));
fesetround(FE_UPWARD); // 设置为向正无穷舍入
show_rounding_mode();
printf("1.75 舍入后: %f\n", rint(num));
fesetround(FE_TONEAREST); // 恢复默认舍入模式
printf("\n");
// 4. 浮点环境保存与恢复
printf("=== 环境保存与恢复 ===\n");
fenv_t env;
fegetenv(&env); // 保存当前环境
// 修改环境
fesetround(FE_TOWARDZERO);
feclearexcept(FE_ALL_EXCEPT);
printf("修改后的环境:\n");
show_rounding_mode();
show_exceptions();
fesetenv(&env); // 恢复原始环境
printf("\n恢复后的环境:\n");
show_rounding_mode();
show_exceptions();
return 0;
}
运行结果:
user@host:~ $ gcc main.c -lm
user@host:~ $ ./a.out=== 初始浮点环境 === 当前浮点异常状态: 无异常 当前舍入模式: 四舍五入 === 触发浮点异常 === 1.0 / 0.0 = inf 当前浮点异常状态: 除零异常 sqrt(-1.0) = -nan 当前浮点异常状态: 除零异常 无效操作异常 === 舍入模式控制 === 当前舍入模式: 向负无穷方向舍入 1.75 舍入后: 1.000000 当前舍入模式: 向正无穷方向舍入 1.75 舍入后: 2.000000 === 环境保存与恢复 === 修改后的环境: 当前舍入模式: 向零舍入 当前浮点异常状态: 无异常 恢复后的环境: 当前舍入模式: 四舍五入 当前浮点异常状态: 除零异常 无效操作异常 不精确结果异常
#类型
类型 | 标准 | 说明 |
---|---|---|
fenv_t | C99 | 表示整个浮点环境的类型 |
fexcept_t | C99 | 表示整个浮点异常标志的类型 |
#函数
函数 | 标准 | 说明 |
---|---|---|
feclearexcep | C99 | 清除指定的浮点异常 |
fetestexcept | C99 | 检查指定的浮点异常 |
feraiseexcept | C99 | 产生指定的浮点异常 |
fegetexceptflag | C99 | 整体获取浮点异常标志 |
fesetexceptflag | C99 | 整体设置浮点异常标志 |
fegetround | C99 | 获取舍入方向 |
fesetround | C99 | 设置舍入方向 |
fegetenv | C99 | 获取浮点环境 |
fesetenv | C99 | 设置浮点环境 |
feholdexcept | C99 | 保存浮点环境并清空浮点异常 |
feupdateenv | C99 | 恢复浮点环境并触发浮点异常 |
#宏
宏 | 标准 | 说明 |
---|---|---|
FE_DFL_ENV | C99 | 指向默认浮点环境的指针 |
浮点数异常宏 | 标准 | 说明 |
---|---|---|
FE_ALL_EXCEPT | C99 | 所有支持的浮点异常的按位或 |
FE_DIVBYZERO | C99 | 浮点运算中发生了极点错误 |
FE_INEXACT | C99 | 结果不精确:需要进行舍入才能存储 |
FE_INVALID | C99 | 浮点运算中发生了域错误 |
FE_OVERFLOW | C99 | 浮点运算的结果太大而溢出 |
FE_UNDERFLOW | C99 | 浮点运算的结果太小而损失精度 |
浮点数舍入方向宏 | 标准 | 说明 |
---|---|---|
FE_DOWNWARD | C99 | 向负无穷方向舍入 |
FE_TONEAREST | C99 | 四舍五入到最接近的可表示值 |
FE_TOWARDZERO | C99 | 向零舍入 |
FE_UPWARD | C99 | 向正无穷方向舍入 |